package com.tanhua.dubbo.server.api;

import com.alibaba.dubbo.config.annotation.Service;
import com.mongodb.client.result.DeleteResult;
import com.tanhua.dubbo.server.pojo.*;
import com.tanhua.dubbo.server.service.IdService;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

@Service(version = "1.0.0") //声明这是一个dubbo服务,程序启动后会将该服务注册到zk的注册中心当中去
public class QuanZiApiImpl implements QuanZiApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdService idService;

    @Override
    public String savePublish(Publish publish) {

        //校验publish对象
        if (null == publish.getUserId()) {
            return null;
        }//可自行增加其他类似校验逻辑

        try {
            //填充publish对象部分信息
            publish.setId(ObjectId.get());//id字段不能由外部调用该set方法进行赋值,我们自己生成
            publish.setCreated(System.currentTimeMillis());
            publish.setSeeType(1);//查看权限默认所有人可见

            //增加自增长的pid:因为mongodb不同于mysql,没有自增的字段功能,因此需要我们自己维护
            publish.setPid(idService.createId("publish", publish.getId().toHexString()));

            //将动态信息写入mongodb的发布表中
            mongoTemplate.save(publish);

            //将动态信息写入自己的相册表中:表名格式quanzi_album_发布动态的用户id
            Album album = new Album();
            album.setId(ObjectId.get());
            album.setPublishId(publish.getId()); //该id为该动态在发布表中的位置
            album.setCreated(System.currentTimeMillis());
            mongoTemplate.save(album, "quanzi_album_" + publish.getUserId());

            //将动态信息写入好友的时间线表中,先要查询有哪些好友:
            Query query = Query.query(Criteria.where("userId").is(publish.getUserId()));
            List<Users> users = mongoTemplate.find(query, Users.class);
            for (Users user : users) {
                TimeLine timeLine = new TimeLine();
                timeLine.setId(ObjectId.get());
                timeLine.setUserId(publish.getUserId()); //每个好友的时间线表中要记录该动态是自己的哪个好友发的
                timeLine.setPublishId(publish.getId());
                timeLine.setDate(System.currentTimeMillis());
                mongoTemplate.save(album, "quanzi_time_line_" + user.getFriendId());
                //此处注意users是tanhua_users表中查询出来的数据,假设当前登录用户id为1(对应userId字段),对应的好友id为2345(对应friendId字段),每一个user都指当前登录用户的一个好友关联信息
            }
            return publish.getId().toHexString();
        } catch (Exception e) {
            e.printStackTrace();
            //TODO 一旦上方往表中写数据出现异常,整个事务回滚
        }
        return null;
    }

    @Override
    public PageInfo<Publish> queryPublishList(Long userId, Integer page, Integer pageSize) {

        Pageable pageable = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("date")));
        Query query = new Query().with(pageable);//此处查询没有筛选条件,只需要对动态的发布时间date做降序排序展示,因此此处没有用Query.query()

        String tableName = "quanzi_time_line_";
        if (null == userId) {
            //查询推荐动态
            tableName += "recommend";
        } else {
            //查询好友动态
            tableName += userId;
        }

        //查询当前登录用户的时间线表/推荐表
        List<TimeLine> timeLines = mongoTemplate.find(query, TimeLine.class, tableName);

        //取出该用户对应的好友/推荐id,封装为list集合
        ArrayList<ObjectId> ids = new ArrayList<>();
        for (TimeLine timeLine : timeLines) {
            ids.add(timeLine.getPublishId());
        }
        //根据时间线表中的publish_id查询发布表中的动态信息
        Query queryPublish = Query.query(Criteria.where("id").in(ids)).with(Sort.by(Sort.Order.desc("created")));
        List<Publish> publishList = mongoTemplate.find(queryPublish, Publish.class);
        PageInfo<Publish> pageInfo = new PageInfo<Publish>(); //不提供数据总数
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(publishList);

        return pageInfo;
    }

    @Override
    public boolean saveLikeComment(Long userId, String publishId) {

        //判断是否已经点赞,如果已经点赞就返回false
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(1);
        Query query = Query.query(criteria);
        long count = mongoTemplate.count(query, Comment.class);
        if (count > 0) {
            return false;
        }

        return this.saveComment(userId, publishId, 1, null); //点赞type默认1
    }

    @Override
    public boolean saveLoveComment(Long userId, String publishId) {

        //判断是否已经喜欢,如果已经喜欢就返回false
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(3);
        Query query = Query.query(criteria);
        long count = mongoTemplate.count(query, Comment.class);
        if (count > 0) {
            return false;
        }

        return this.saveComment(userId, publishId, 3, null); //喜欢type默认3
    }

    @Override
    public boolean removeComment(Long userId, String publishId, Integer commentType) {

        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(commentType);
        Query query = Query.query(criteria);
        DeleteResult deleteResult = mongoTemplate.remove(query, Comment.class);

        return deleteResult.getDeletedCount() > 0;
    }

    @Override
    public boolean saveComment(Long userId, String publishId, Integer type, String content) {

        try {

            Comment comment = new Comment();
            comment.setContent(content);
            comment.setCommentType(type);
            comment.setCreated(System.currentTimeMillis());
            comment.setId(ObjectId.get());
            comment.setPublishId(new ObjectId(publishId));
            comment.setUserId(userId);//评论人id
            comment.setIsParent(true);
            //设置发布人id
            Publish publish = mongoTemplate.findById(comment.getPublishId(), Publish.class);
            //查完发布表&视频表都没有找到对应的记录,证明这个publishId是非法传入的
            if (null != publish) {
                comment.setPublishUserId(publish.getUserId());
            } else {
                Video video = mongoTemplate.findById(comment.getPublishId(), Video.class);
                if (null != video) {
                    comment.setPublishUserId(video.getUserId());
                }
            }
            //comment.setParentId(); 暂无不做设置
            mongoTemplate.save(comment);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Long queryCommentCount(String publishId, Integer type) {

        Criteria criteria = Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(type);
        Query query = Query.query(criteria);

        return mongoTemplate.count(query, Comment.class);
    }

    @Override
    public Publish queryPublishById(String publishId) {

        return this.mongoTemplate.findById(new ObjectId(publishId), Publish.class);
    }

    @Override
    public PageInfo<Comment> queryCommentList(String publishId, Integer page, Integer pageSize) {

        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.asc("created")));
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(2)).with(pageRequest);
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);

        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setPageSize(pageSize);
        pageInfo.setPageNum(page);
        pageInfo.setRecords(commentList);

        return pageInfo;
    }

    @Override
    public PageInfo<Comment> queryCommentListByUser(Long userId, Integer type, Integer page, Integer pageSize) {

        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query(Criteria
                .where("publishUserId").is(userId)//发表动态的用户
                .and("commentType").is(type)).with(pageRequest);

        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);

        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(commentList);
        return pageInfo;
    }

    @Override
    public List<Publish> queryPublishByPids(List<Long> pids) {

        Query query = Query.query(Criteria.where("pid").in(pids));
        return mongoTemplate.find(query, Publish.class);
    }

    @Override
    public PageInfo<Publish> queryAlbumList(Long userId, Integer page, Integer pageSize) {

        PageInfo<Publish> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        Pageable pageable = PageRequest.of(page-1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query().with(pageable);
        List<Album> albumList = mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);
        if (CollectionUtils.isEmpty(albumList)) {
            return pageInfo;
        }

        //查询相册表中对应的动态信息
        ArrayList<ObjectId> publicIds = new ArrayList<>();
        for (Album album : albumList) {
            publicIds.add(album.getPublishId());
        }

        Query queryPublish = Query.query(Criteria.where("id").in(publicIds)).with(Sort.by(Sort.Order.desc("created")));
        List<Publish> publishList = mongoTemplate.find(queryPublish, Publish.class);

        pageInfo.setRecords(publishList);
        return pageInfo;
    }
}
